<?php
// 基础类
namespace interface\v1;

use PYClass;
use control\interfaces as API;
use JetBrains\PhpStorm\ArrayShape;

require_once '../../control/interface.php';
require_once '../../control/verify.php';

trait app
{
	use API;
	
	/**
	 * 时间比较，用于生成SQL
	 *
	 * @param string $str
	 * @param string $type
	 * @param string $field
	 * @return string
	 */
	public static function miniTimeComparison(string $str, string $type = 'date', string $field = 'time'): string
	{
		$sqlString = '';
		if ($str) {
			$data = match ($str) {
				'今天'    => [
					date('Y-m-d'),
					date('Y-m-d'),
				],
				'近7天'   => [
					date('Y-m-d', strtotime("-7 day")),
					date('Y-m-d'),
				],
				'近30天'  => [
					date('Y-m-d', strtotime("-30 day")),
					date('Y-m-d'),
				],
				default => explode('~', $str),
			};
			
			if (is_array($data)) {
				$startStamp = strtotime(trim($data[0]));
				$endStamp   = strtotime(trim(end($data)));
				switch ($type) {
					case 'day':
					case 'date':
						$format    = 'Y-m-d';
						$formatSql = '%Y-%m-%d';
						break;
					case 'mon':
					case 'month':
						$format    = 'Y-m';
						$formatSql = '%Y-%m';
						break;
					case 'year':
						$format    = 'Y';
						$formatSql = '%Y';
						break;
					case 'time':
					default:
						$format    = 'Y-m-d H:i:s';
						$formatSql = '%Y-%m-%d %H:%i:%s';
						break;
				}
				$sqlString = " AND date_format($field, '$formatSql') >= '" . date($format, $startStamp) . "'  AND  date_format($field, '$formatSql') <= '" . date($format, $endStamp) . "' ";
			}
		}
		return $sqlString;
	}
	
	/**
	 * 给文件或图片地址填充完整路径
	 */
	public static function fillSrc($src, $suffix = '')
	{
		if (!str_contains($src, 'www.')) {
			$src = root . $src;
		}
		if ($suffix) {
			$src .= '?v=' . $suffix;
		}
		return $src;
	}
	
	/*日志
	$data = array(
		"type" => "configure.php中的权限类型，如job，client",
		"text" => "日志说明",
	);
	*/
	public function logText($data, $isIgnore = false): bool|string
	{
		$finger = 0;
		//检查权限
		foreach ($this->powerAll as $twoArray) {
			foreach ($twoArray as $threeArray) {
                unset($threeArray['attribute']);
				if (array_key_exists($data['type'], $threeArray)) {
					$finger = 2;
				}
			}
		}
		if ($isIgnore) {
			$finger = 2;
		}
		//判断
		if ($finger != 2) {
			test("【" . $data['text'] . "】日志插入失败，原因：未找到权限类型");
		} elseif (empty($data['text'])) {
			test("【" . $data['type'] . "】日志插入失败，原因：日志说明为空");
		} else {
			if (empty($data['stid'])) {
				$data['stid'] = self::$stid;
			}
			$data['time'] = date("Y-m-d H:i:s");
			return insert(["table" => "log", "field" => $data]);
		}
		return false;
	}
	
	/**
	 * 权限函数
	 *
	 * @param string $page
	 * @param string $power
	 */
	public function power(string $page, string $power): bool
	{
		return in_array($power, isset($this->controlPower[$page]) ? (array)$this->controlPower[$page] : []);
	}
	
	/**
	 * 获取用户权限
	 *
	 * @return array
	 */
	public static function getUserPower(): array
	{
		$array     = [];
		$roleArray = (array)json_decode(self::$user['role'] ?? '', true);
		if ($roleArray) {
			foreach ($roleArray as $id) {
				$role  = query('role', " id = '$id' ");
				$temp  = isset($role['power']) ? (array)json_decode($role['power'], true) : [];
				$array = array_merge($array, $temp);
			}
		}
		return $array;
	}
	
	/*分页
	$data = array(
		"table" => "要查询的表名称",
		"where" => "查询条件",
		"order" => "排序方式",
		"num" => "每页返回记录条数",
	);
	*/
	public function page($data): array
	{
		$data['field'] = $data['field'] ?? '';
		//修正每页返回记录条数
		if (empty($data['num']) or preg_match(checkInteger, $data['num']) == 0) {
			$data['num'] = 20;
		}
		//总条数
		$sqlNum = self::total(array('table' => $data['table'], 'where' => $data['where'])); //总条数
		//总页数
		$pageAll = ceil($sqlNum / $data['num']);
		//修正当前页
		if (preg_match(checkString, $this->get('page')) == 0 or $this->get('page') <= 0) {
			$pageNow = 1;
		} else {
			$pageNow = $this->get('page');
		}
		//数据库查询结果
		$sqlFirst = ($pageNow - 1) * $data['num'];                                          //当前页面开始位置
		$sqlTable = find(array("table" => $data['table'], "field" => $data['field'], "where" => $data['where'] . " order by " . $data['order'] . " limit " . $sqlFirst . "," . $data['num']));
		if (is_array($sqlTable)) {
			$result['sql']   = $sqlTable['sql'];
			$result['array'] = $sqlTable['array'];
		} else {
			$result['sql']   = $sqlTable;
			$result['array'] = [];
		}
		//返回
		$result['para'] = array(
			"sqlNum"  => $sqlNum,//总条数
			"pageAll" => $pageAll,//总页数
			"pageNow" => $pageNow,//当前页
		);
		return $result;
	}
	
	/*数据库排序
	$data = array(
		"search" => "查询关键词",
		"default" => "默认排序关键词",
		"array" => array(//排序字典
			"排序字段名称" => array(
				"asc" => "本字段升序排序关键词",
				"desc" => "本字段降序排序关键词",
				"site" => "本字段在表格中列的位置",
			),
		),
	);
	*/
	public function orderBy($data): array
	{
		//有查询条件
		if (!empty($data['search'])) {
			$para = $this->orderByEach(array("search" => $data['search'], "array" => $data['array']));
		}
		//如未找到，则查询默认
		if (empty($para['orderBy'])) {
			$para = $this->orderByEach(array("search" => $data['default'], "array" => $data['array']));
		}
		//返回
		return $para;
	}
	
	/*数据库排序-循环数组
	$data = array(
		"search" => "查询关键词",
		"array" => "排序字典",
	);
	*/
	#[ArrayShape(['field' => "mixed|null|string", "orderBy" => "string", 'site' => "mixed|null|string", "style" => "string"])] public function orderByEach($data): array
	{
		//参数准备
		$para = array(
			"field"   => "",//sql查询自定义字段
			"orderBy" => "",//sql查询排序代码
			"site"    => "",//排序标记列的位置
			"style"   => "",//排序标记样式
		);
		//遍历排序字典
		foreach ($data['array'] as $name => $array) {
			foreach ($array as $key => $value) {
				if ($data['search'] == $value) {
					$para['orderBy'] = $name . " " . $key;
					$para['field']   = $array['field'] ?? null;
					$para['site']    = $array['site'] ?? null;
					//排序标签
					if ($key == "desc") {
						$para['style'] = orderByDescStyle;
					} elseif ($key == "asc") {
						$para['style'] = orderByAscStyle;
					}
				}
			}
		}
		//返回
		return $para;
	}
	
	/**
	 * 查看自己
	 *
	 * @param string $page
	 * @param string $field
	 * @return string
	 */
	public function seeSelf(string $page, string $field = 'stid'): string
	{
		if (empty($this->control['stid'])) {
			return '';
		}
		$where = '';
		if (!$this->power($page, 'seeAll')) {
			$where = " and $field = '{$this->control['stid']}' ";
		}
		return $where;
	}
	
	/** 根据编码规则生成编码
	 *
	 * @param string $page
	 * @param array  $data
	 * @param array  $field
	 * @return string
	 */
	public static function generateCode(string $page, array $data, array $field): string
	{
		$query          = query('code_template', " menuThree = '$page' and state = '启用' ");
		$query['split'] = $query['split'] == '无' ? '' : $query['split'];
		$code           = "";
		$prefix         = "";
		if (!empty($query['id'])) {
			$body = json_decode($query['body'], true);
			foreach ((array)$body as $k => $val) {
				$splicing = true; //拼接编码段标识
				switch ($val['type']) {
					case '常量':
						$code   .= $val['setValue'];
						$prefix .= $val['setValue'] . $query['split'];
						break;
					case '日期':
						$date = date('Ymd');
						if ($val['setValue'] == 'yyMMdd') {
							$date = date('ymd');
						}
						$code .= $date;
						if ($val['setValue2'] == 1) {
							$prefix .= $date . $query['split'];
						}
						break;
					case '业务字段':
						$wrod = isset($field[$val['setValue']])?$field[$val['setValue']]:'';
						if($wrod) {
							$pinyin = strtoupper(PYClass::encode($wrod));
							$code .= $pinyin;
							if ($val['setValue2'] == 1) {
								$prefix .= $pinyin . $query['split'];
							}
						}else {
							$splicing = false;
						}
						break;
					case '流水号':
						$table   = $data['table'] ?? 'user';
						$field   = $data['field'] ?? 'orderNo';
						$where   = $data['where'] ?? '';
						$index   = $data['index'] ?? 1;
						$length  = $val['setValue']; //填充位长度
						$default = str_pad($val['setValue2'], $length, '0', STR_PAD_LEFT);
						$res     = query($table, " `$field` LIKE '$prefix%' $where  ORDER BY $field DESC ");
						if (!$res[$field]) {
							$code .= $default;
						} else {
							//(int)$temp = str_replace($prefix, '', $res[$field]);
							(int)$temp = substr($res[$field], -1 * $length);
							$code .= (str_pad((intval($temp) + $index), $length, '0', STR_PAD_LEFT));
						}
						break;
					default:
				}
				if ($k != count($body) - 1 && $splicing) {
					$code .= $query['split'];
				}
			}
		}
		if (empty($code)) {
			$code = self::generateNo($data);
		}
		return $code;
	}
}